/*
 * Copyright (C) 2019 Peng fei Pan <panpfpanpf@outlook.me>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package me.panpf.sketch.process;

import me.panpf.sketch.Sketch;
import me.panpf.sketch.cache.BitmapPool;
import me.panpf.sketch.request.Resize;
import me.panpf.sketch.zoom.PixmapBuild;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Matrix;
import ohos.agp.utils.Point;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;

import java.util.Locale;

/**
 * 倒影图片处理器
 */
@SuppressWarnings("WeakerAccess")
public class ReflectionImageProcessor extends WrappedImageProcessor {

    private static final int DEFAULT_REFLECTION_SPACING = 2;
    private static final float DEFAULT_REFLECTION_SCALE = 0.3f;

    private int reflectionSpacing;
    private float reflectionScale;

    /**
     * 创建一个倒影图片处理器
     *
     * @param reflectionSpacing 倒影和图片之间的距离
     * @param reflectionScale 倒影的高度所占原图高度比例，取值为 0 到 1
     * @param wrappedImageProcessor 嵌套一个图片处理器
     */
    public ReflectionImageProcessor(int reflectionSpacing, float reflectionScale, WrappedImageProcessor wrappedImageProcessor) {
        super(wrappedImageProcessor);
        this.reflectionSpacing = reflectionSpacing;
        this.reflectionScale = reflectionScale;
    }

    /**
     * 创建一个倒影图片处理器
     *
     * @param reflectionSpacing 倒影和图片之间的距离
     * @param reflectionScale 倒影的高度所占原图高度比例，取值为 0 到 1
     */
    public ReflectionImageProcessor(int reflectionSpacing, float reflectionScale) {
        this(reflectionSpacing, reflectionScale, null);
    }

    /**
     * 创建一个倒影图片处理器，默认倒影和图片之间的距离是 2 个像素，倒影的高度所占原图高度比例是 0.3
     *
     * @param wrappedImageProcessor 嵌套一个图片处理器
     */
    public ReflectionImageProcessor(WrappedImageProcessor wrappedImageProcessor) {
        this(DEFAULT_REFLECTION_SPACING, DEFAULT_REFLECTION_SCALE, wrappedImageProcessor);
    }

    /**
     * 创建一个倒影图片处理器，默认倒影和图片之间的距离是 2 个像素，倒影的高度所占原图高度比例是 0.3
     */
    public ReflectionImageProcessor() {
        this(DEFAULT_REFLECTION_SPACING, DEFAULT_REFLECTION_SCALE, null);
    }

    @Override
    public PixmapBuild onProcess(Sketch sketch, PixmapBuild bitmap, Resize resize, boolean lowQualityImage) {
        if (bitmap.getPixelMap().isReleased()) {
            return bitmap;
        }

        int srcHeight = bitmap.getPixelMap().getImageInfo().size.height;
        int reflectionHeight = (int) (srcHeight * reflectionScale);
        int reflectionTop = srcHeight + reflectionSpacing;
        PixelFormat config = lowQualityImage ? PixelFormat.UNKNOWN : PixelFormat.ARGB_8888;
        BitmapPool bitmapPool = sketch.getConfiguration().getBitmapPool();

        PixmapBuild reflectionBitmap = bitmapPool.getOrMake(bitmap.getPixelMap().getImageInfo().size.width, reflectionTop + reflectionHeight, config);

        // 在上半部分绘制原图
        Canvas canvas = new Canvas(new Texture(reflectionBitmap.getPixelMap()));
//        canvas.drawBitmap(bitmap, 0, 0, null);
        canvas.drawPixelMapHolder(new PixelMapHolder(bitmap.getPixelMap()), 0, 0, new Paint());

        // 在下半部分绘制倒影
        Matrix matrix = new Matrix();
        matrix.postScale(1, - 1);
        matrix.postTranslate(0, srcHeight + reflectionTop);
//        canvas.drawBitmap(bitmap, matrix, null);

        PixelMapHolder pixelMapHolder = new PixelMapHolder(bitmap.getPixelMap());
        canvas.setMatrix(matrix);
        canvas.drawPixelMapHolder(pixelMapHolder, 0, 0, new Paint());

        //重置矩阵
        canvas.resetMatrix();

        // 在倒影部分绘制半透明遮罩，让倒影部分产生半透明渐变的效果
        Paint paint = new Paint();
//        paint.setShader(new LinearGradient(0, reflectionTop, 0, reflectionBitmap.getHeight(), 0x70ffffff, 0x00ffffff, TileMode.CLAMP));
        Point p1 = new Point(0, reflectionTop);
        Point p2 = new Point(0, reflectionBitmap.getPixelMap().getImageInfo().size.height);

        Point[] points = {p1, p2};
        Color[] colors = {new Color(0x70ffffff), new Color(0x00ffffff)};
        LinearShader linearShader = new LinearShader(points, null, colors, Shader.TileMode.CLAMP_TILEMODE);

        paint.setShader(linearShader, Paint.ShaderType.LINEAR_SHADER);
//        paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
        paint.setBlendMode(BlendMode.DST_IN);
        canvas.drawRect(0, reflectionTop, reflectionBitmap.getPixelMap().getImageInfo().size.width, reflectionBitmap.getPixelMap().getImageInfo().size.height, paint);

        return reflectionBitmap;
    }

    public float getReflectionScale() {
        return reflectionScale;
    }

    public int getReflectionSpacing() {
        return reflectionSpacing;
    }

    @Override
    public String onToString() {
        return String.format(Locale.US, "%s(scale=%s,spacing=%d)", "ReflectionImageProcessor", reflectionScale, reflectionSpacing);
    }

    @Override
    public String onGetKey() {
        return String.format(Locale.US, "%s(scale=%s,spacing=%d)", "Reflection", reflectionScale, reflectionSpacing);
    }
}
